#pragma once

#include "InetAddr.hpp"
#include "Log.hpp"

#define BACKLOG 8

static const int defaultsockfd = -1;


namespace TcpServerArea
{
    using namespace LogArea;

    using func_t = std::function<std::string(std::string&)>;
    using task_t = std::function<void()>;

    class TcpServer
    {
        struct ThreadData
        {
            int sockfd;
            TcpServer* self;
        };
    public:
        TcpServer(func_t func) : _listen_sockfd(defaultsockfd), _port(defaultport), _is_running(false),_func(func)
        {
        }

        void InitServer()
        {
            // 创建套接字
            _listen_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
            if (_listen_sockfd < 0)
            {
                LOG(LogLevel::FATALER) << "socket error";
                DIE(SOCKET_ERR);
            }
            LOG(LogLevel::INFO) << "socket success, sockfd is: " << _listen_sockfd;

            // 填充信息
            struct sockaddr_in server;
            memset(&server, 0, sizeof(server));
            server.sin_family = AF_INET;
            server.sin_port = ::htons(_port);
            server.sin_addr.s_addr = INADDR_ANY;

            // 绑定
            int n = ::bind(_listen_sockfd, CONV(&server), sizeof(server));
            if (n < 0)
            {
                LOG(LogLevel::FATALER) << "bind error";
                DIE(BIND_ERR);
            }
            LOG(LogLevel::INFO) << "bind success, sockfd is: " << _listen_sockfd;

            // 监听链接 BACKLOG:排队等待接听的最大长度
            n = ::listen(_listen_sockfd, BACKLOG);
            if (n < 0)
            {
                LOG(LogLevel::FATALER) << "listen error";
                DIE(LISTEN_ERR);
            }
            LOG(LogLevel::INFO) << "listen success, sockfd is: " << _listen_sockfd;
        }

        void HandlerRequest(int sockfd)
        {
            LOG(LogLevel::INFO) << "HandlerRequest, sockfd is : " << sockfd;
            char inbuffer[4096];
            std::string message;
            while (true)
            {
                // ssize_t n = ::read(sockfd,inbuffer,sizeof(inbuffer)-1); 

                //客户端传过来序列化的数据
                ssize_t n = ::recv(sockfd, inbuffer, sizeof(inbuffer) - 1, 0); //recv、send专门用于网络通信
                if (n > 0)
                {
                    inbuffer[n] = 0;
                    LOG(LogLevel::DEBUG)<<"\n"<<inbuffer;

                    //需要判断读取到的是完整的数据
                    message+=inbuffer; //len\r\n{json}\r\n 

                    std::string result = _func(message);
                    if(result.empty()) continue;
                    // std::string message = "echo # ";
                    // std::string result = std::to_string(sockfd) + "say: ";
                    // // inbuffer[n] = 0;
                    // // std::string message;
                    // if(strcmp(inbuffer,"quit") == 0)
                    //     result += "我走了哈,你们聊!";
                    // else
                    //     result+=inbuffer;
                    // LOG(LogLevel::INFO)<<message;

                    // std::string info = "echo# ";
                    // info += inbuffer;

                    // // 向客户端回显
                    // //  ssize_t size = ::write(sockfd,info.c_str(),info.size());
                    // ssize_t size = ::send(sockfd, info.c_str(), info.size(), 0);
                    // LOG(LogLevel::INFO)<<result;

                    //将序列化+封装后的计算结果穿回给客户端
                    ::send(sockfd,result.c_str(),result.size(),0);
                }
                else if(n==0)
                {
                    //表示客户端退出
                    LOG(LogLevel::INFO)<<"client quit: "<<sockfd;
                    break;
                }
                else break; //读取失败
            }
        }

        static void* ThreadEntry(void* args)
        {
            pthread_detach(pthread_self());
            ThreadData* peer = (ThreadData*)args;
            peer->self->HandlerRequest(peer->sockfd);
            return nullptr;
        }

        void Start()
        {
            _is_running = true;
            while (_is_running)
            {
                // 获取客户端的地址信息
                struct sockaddr_in peer;
                socklen_t peerlen = sizeof(peer);

                // 接受请求
                int sockfd = ::accept(_listen_sockfd, CONV(&peer), &peerlen);
                if (sockfd < 0)
                {
                    LOG(LogLevel::WARNING) << "accept warning";
                    continue;
                }

                //多进程版本
                // pid_t pid = ::fork();
                // if(pid==0)
                // {
                //     //子进程
                //     ::close(_listen_sockfd);  //关闭不需要的 fd
                //     //孙子进程
                //     if(fork() > 0) exit(0); //孙子进程的父进程退出, 孙子进程继续执行Handler,孙子进程变成孤儿进程，由系统抚养
                //     HandlerRequest(sockfd, peer);
                //     exit(0);
                // }

                // ::close(sockfd);  //sockfd 交由子进程进行服务, 父进程关闭
                // int rid = ::waitpid(pid,nullptr,0);
                // if(rid<0)
                //     LOG(LogLevel::ERROR)<<"waitpid error";


                // //多线程版本简易
                // // 主线程和新线程是如何看待：文件描述符表，共享一张文件描述符表！！
                // pthread_t tid;
                // ThreadData* data = new ThreadData;
                // data->sockfd = sockfd;
                // data->self = this;
                // pthread_create(&tid,nullptr,ThreadEntry,data);


                //多线程 线程池版本
                ThreadPool<task_t>::GetInstance()->Equeue([this,sockfd](){
                    this->HandlerRequest(sockfd);
                }); 

                LOG(LogLevel::INFO) << "accept success,sockfd is: " << sockfd;
            }
            Stop();
        }

        void Stop()
        {
            _is_running = false;
        }
        ~TcpServer()
        {
        }

    private:
        int _listen_sockfd;
        uint16_t _port;

        bool _is_running;

        func_t _func;
    };
}